#include "Homework2.h"
#include "SingleBufferManager.h"
#include "SortedBufferManager.h"
#include "Homework1_Test.h"
#include "Homework4.h"
#include "SegmentInventory.h"
#include "GlobalStuff.h"
#include "SegmentInventory_Test.h"
#include "Index.h"
#include "Comparator_Test.h"

#include "IndexVisualizer.h"

#include "Index_Test.cpp"

void createTestFile(unsigned multiplier)
{
    //Create TestFile
    FILE* testFile = fopen(fileName, "w");
    char* data = new char[multiplier * pageSize];

    for (unsigned i = 0; i < multiplier; i++)
    {
        for (unsigned j = 0; j < pageSize; j++)
        {
            data[i * pageSize + j] = (char)i;
        }
    }

    fwrite((void*)data, sizeof(char), multiplier * pageSize, testFile);
    fclose(testFile);

    delete[] data;
}



void testLookup()
{
	createTestFile(50);
	Index<unsigned> index;
	cout << "begin: testLookup()" << endl;

	for(unsigned i = 0; i < 10000; i++)
	{
	    cout << i << endl;
		TID tid;
		tid.pageId = i;
		tid.slotId = i;
		index.insert(i, tid);
		//if (i==112) {
        //    IndexVisualizer vis;
        //    index.visualize(vis);
        //    vis.saveAs("TestInsert" + IndexVisualizer::toString(i) + ".png");
		//}

		TID tid_ist = index.lookup(i);
		assert(tid_ist.pageId == i);
		assert(tid_ist.slotId == i);
	}

	for(unsigned i = 0; i < 10000; i++)
	{
		TID tid_ist = index.lookup(i);
		assert(tid_ist.pageId == i);
		assert(tid_ist.slotId == i);
	}

	IndexVisualizer vis;
    index.visualize(vis);
	vis.saveAs("TestLookUp.png");
}

void testLookup_Random()
{
	createTestFile(50);
	Index<unsigned> index;
	cout << "begin: testLookup_Random()" << endl;

	vector<unsigned> usedValues;
    unsigned testSize = 10000;

	for(unsigned i = 0; i < testSize; i++)
	{
	    cout << i << endl;
		TID tid;
		tid.pageId = i;
		tid.slotId = i;

		unsigned key;
		bool contains = true;

		while(contains)
		{
		    key = random() % (100 * testSize);
		    for(unsigned x = 0; x <= usedValues.size(); x++)
		    {
		        if(x == usedValues.size())
		        {
		            contains = false;
		        }
		        else if(usedValues[x] == key)
		        {
		            break;
		        }
		    }
		}
		cout << "key: " << key << endl;
		usedValues.push_back(key);

		index.insert(key, tid);
	}

	for(unsigned i = 0; i < usedValues.size(); i++)
	{
		TID tid_ist = index.lookup(usedValues[i]);
		assert(tid_ist.pageId == i);
		assert(tid_ist.slotId == i);
	}
}

void testInsert()
{
    createTestFile(50);
    Index<long> index;
    cout << "begin" << endl;
    unsigned step = 0;
	for(long i = 1; i <= 70; i++)
	{
	    cout << i << endl;
	    TID tid;
	    tid.pageId = i;
	    tid.slotId = i;
		index.insert(i, tid);
		IndexVisualizer vis;
        index.visualize(vis);
		vis.saveAs("TestInsert" + IndexVisualizer::toString(step) + ".png");
		step ++;
	}

    cout << "ready"<<endl;
}

void testInsert_Large()
{
    createTestFile(50);
    Index<long> index;
    cout << "begin" << endl;
    unsigned step = 0;
	for(long i = 1; i <= 100000; i++)
	{
	    cout << i << endl;
	    TID tid;
	    tid.pageId = i;
	    tid.slotId = i;
		index.insert(i, tid);
		step ++;
	}

    cout << "ready"<<endl;
}

void testLookupRange()
{
	createTestFile(50);
	Index<unsigned> index;
	cout << "begin: testLookupRange()" << endl;
	unsigned testCount = 10000;
	cout << "creating Tree" << endl;
	for(unsigned i = 0; i < testCount; i++)
	{
	    cout << i << endl;
		TID tid;
		tid.pageId = i;
		tid.slotId = i;
		index.insert(i, tid);
	}

	cout << "Tree created - running test" << endl;

	for(unsigned i = 0; i < testCount / 10; i++)
	{
	    cout << "Run " << i << endl;
		unsigned x = random() % testCount;
		unsigned y = random() % testCount;
		unsigned lower = (x <  y)?x:y;
		unsigned upper = (x >= y)?x:y;

		cout << "Lower: " << lower << endl;
		cout << "Upper: " << upper << endl;

		index_iterator it = index.lookupRange(lower, upper);

		while(it != it.end())
		{
			TID t = *it;
			assert(lower == t.pageId);
			assert(lower == t.slotId);
			lower++;
			it++;
		}
		assert(lower - 1 == upper);
	}

	cout << "end TestLookUpRange" << endl;
}

void testInsert_Random()
{
	createTestFile(50);
	Index<unsigned> index;
	cout << "begin: testInsert_Random()" << endl;

    unsigned testSize = 90000;
    unsigned x = 0,y = 30000,z = 60000;
    unsigned x_max = y, y_max = z, z_max = testSize;

	for(unsigned i = 0; i < testSize; i++)
	{
	    cout << i << endl;
        unsigned key = testSize + 1;

        while(key == testSize + 1)
        {
            switch(rand() % 3)
            {
                case 0:
                    if(x < x_max) key = x++;
                    break;
                case 1:
                    if(y < y_max) key = y++;
                    break;
                default:
                    if(z < z_max) key = z++;
                    break;
            }
        }
		TID tid;
		tid.pageId = key;
		tid.slotId = key;

		cout << "key: " << key << endl;
		index.insert(key, tid);
	}

	for(unsigned i = 0; i < testSize; i++)
	{
		TID tid_ist = index.lookup(i);
		assert(tid_ist.pageId == i);
		assert(tid_ist.slotId == i);
	}
}

void testRemove()
{
    createTestFile(50);
    Index<long> index;
    cout << "testRemove" << endl;
    unsigned step = 0;
	for(long i = 1; i <= 44; i++)
	{
	    cout << i << endl;
	    TID tid;
	    tid.pageId = i;
	    tid.slotId = i;
		index.insert(i, tid);
		step ++;
	}

	int x = 0;

    for(long i = 13; i <= 24; i++)
    {
        cout << i << endl;
        index.remove(i);
            IndexVisualizer vis2;
            index.visualize(vis2);
            vis2.saveAs("F" + IndexVisualizer::toString(x) + "TestRemove_after" + IndexVisualizer::toString(i) + ".png");
            x++;
    }

    for(long i = 1; i <= 12; i++)
    {
        cout << i << endl;
        index.remove(i);
            IndexVisualizer vis2;
            index.visualize(vis2);
            vis2.saveAs("TestRemove_after" + IndexVisualizer::toString(i) + ".png");
            x++;
    }

    for(long i = 25; i <= 44; i++)
    {
        cout << i << endl;
        index.remove(i);
            IndexVisualizer vis2;
            index.visualize(vis2);
            vis2.saveAs("TestRemove_after" + IndexVisualizer::toString(i) + ".png");
            x++;
    }


    popen("rm ./images/*.dot", "r");
    cout << "ready"<<endl;
}

void testRemove_Random()
{
	createTestFile(50);
	Index<unsigned> index;
	cout << "begin: testInsert_Random()" << endl;

    //unsigned testSize = 90000;
    unsigned testSize = 60;

    for(unsigned i = 0; i < testSize; i++)
    {
        TID tid;
        tid.slotId = i;
        tid.pageId = i;
        index.insert(i, tid);
    }

    cout << "index created" << endl;

    //unsigned x = 0,y = 30001,z = 60001;
    unsigned x = 0,y = 20,z = 40;
    unsigned x_max = y - 1, y_max = z - 1, z_max = testSize;

	for(unsigned i = 0; i < testSize - 2; i++)
	{
	    cout << i << endl;
        unsigned key = testSize + 1;

        while(key == testSize + 1)
        {
            switch(rand() % 3)
            {
                case 0:
                    if(x < x_max) key = x++;
                    break;
                case 1:
                    if(y < y_max) key = y++;
                    break;
                default:
                    if(z < z_max) key = z++;
                    break;
            }
        }
		TID tid;
		tid.pageId = key;
		tid.slotId = key;

		cout << "key: " << key << endl;
		TID ist = index.lookup(key);
		assert(ist.slotId == tid.slotId);

	//	assert(index.remove(key));
        index.remove(key);

//		if(i % 1 == 100)
	//	{
            //IndexVisualizer vis2;
           // index.visualize(vis2);
          //  vis2.saveAs("F" + IndexVisualizer::toString(i) + "TestRemove_after" + IndexVisualizer::toString(key) + ".png");
		//}
	}
}

void debug4()
{
	createTestFile(50);
	Index<unsigned> index;
	cout << "begin: debug4" << endl;

    unsigned testSize = 60;

    for(unsigned i = 0; i < testSize; i++)
    {
        TID tid;
        tid.slotId = i;
        tid.pageId = i;
        index.insert(i, tid);
    }

    unsigned* data = new unsigned[43];
    unsigned x = 0;

    data[x++] = 20;
    data[x++] = 0;
    data[x++] = 40;
    data[x++] = 21;
    data[x++] = 1;
    data[x++] = 2;
    data[x++] = 3;
    data[x++] = 4;
    data[x++] = 22;
    data[x++] = 23;
    data[x++] = 5;
    data[x++] = 6;
    data[x++] = 41;
    data[x++] = 24;
    data[x++] = 7;
    data[x++] = 8;
    data[x++] = 9;
    data[x++] = 25;
    data[x++] = 42;
    data[x++] = 43;
    data[x++] = 10;
    data[x++] = 44;
    data[x++] = 45;
    data[x++] = 46;
    data[x++] = 26;
    data[x++] = 27;
    data[x++] = 11;
    data[x++] = 12;
    data[x++] = 47;
    data[x++] = 13;
    data[x++] = 28;
    data[x++] = 14;
    data[x++] = 15;
    data[x++] = 16;
    data[x++] = 29;
    data[x++] = 30;
    data[x++] = 31;
    data[x++] = 32;
    data[x++] = 33;
    data[x++] = 34;
    data[x++] = 17;
    data[x++] = 18;
    data[x++] = 35;

    for(unsigned i = 0; i < 43; i++)
    {
        cout << data[i] << " - ";
        if(index.remove(data[i]))
            cout << "true" << endl;
        else
            cout << "false" << endl;

        if(true)//i >= 36)
        {
            IndexVisualizer vis2;
            index.visualize(vis2);
            vis2.saveAs("F" + IndexVisualizer::toString(i) + "TestRemove_after" + IndexVisualizer::toString(data[i]) + ".png");
        }
    }

    delete[] data;
    DB::getDB().destroyDB();

    usleep(1000 * 20000);
}

int main()
{
    srand(time(0));

    //testInsert_Large();
    //testInsert_Random();
    //testInsert();
	//testLookup();
	//testLookup_Random();
	//testLookupRange();
	//debug2();
	//testRemove();
	//testRemove_Random();
	debug4();


	//Aufräumen
	//popen("rm ./images/*.dot" , "r");

	//SLEEP(15000);


    //testing::InitGoogleTest(&argc, argv);
    //RUN_ALL_TESTS();
    /*
    Index_Iterator_Test();

    Index<int> index;
    Index<int> index2(2);
    Index<int> i;
    i.insert(0, TID());
    i.lookupRange(0, 1);

    Comparator_Test<int>::runTest();
*/

    ///////////////////////Homework4_Tests//////////////////////////
    //Homework4::test1();
    //Homework4::test2();
    //Homework4::test3();
    //Homework4::test4();
    //Homework4::test5();

    ///////////////////////Homework3_Tests//////////////////////////

    //Hausaufgabe3_Test::test1();
    //Hausaufgabe3_Test::test2();
    //Hausaufgabe3_Test::test3();
    //Hausaufgabe3_Test::test4();
    //Hausaufgabe3_Test::test5();
    //Hausaufgabe3_Test::test6(); //probs
    //Hausaufgabe3_Test::test7();


    ///////////////////////Homework1_Tests//////////////////////////
    /*
        Homework1_Test<SingleBufferManager> h1_sing;
        h1_sing.fullTest();

        Homework1_Test<SortedBufferManager> h1_sort;
        h1_sort.fullTest();
    */
    ///////////////////////Homework2_Tests//////////////////////////
    /*
        cout << "----------SingleBufferManager----------" << endl;
        Homework2<SingleBufferManager> h;
        h.startTest(fileName, 10);

        cout << endl << "----------SortedBufferManager----------" << endl;
        Homework2<SortedBufferManager> h_sort;
        h_sort.startTest(fileName, 10);
    */
    return 0;
}
